home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / oleo-1_4.lha / oleo-1.4 / window.c < prev    next >
C/C++ Source or Header  |  1993-05-21  |  34KB  |  1,642 lines

  1. /*    Copyright (C) 1992, 1993 Free Software Foundation, Inc.
  2.  
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2, or (at your option)
  6. any later version.
  7.  
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11. GNU General Public License for more details.
  12.  
  13. You should have received a copy of the GNU General Public License
  14. along with this software; see the file COPYING.  If not, write to
  15. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  16.  
  17. #include <stdio.h>
  18. #include "global.h"
  19. #include "window.h"
  20. #include "io-generic.h"
  21. #include "io-abstract.h"
  22. #include "io-utils.h"
  23. #include "io-term.h"
  24. #include "cmd.h"
  25. #include "lists.h"
  26. #include "regions.h"
  27.  
  28. int scr_lines = 24;
  29. int scr_cols = 80;
  30. #define LINES scr_lines
  31. #define COLS scr_cols
  32.  
  33.  
  34. /* These control the layout of input and status lines. */
  35. int user_input = 1;        /* As specified (+/- [0-2]). */
  36. int user_status = 2;
  37. int input = 0;            /* As row address. */
  38. int status = 1;
  39. int input_rows = 1;        /* Size of input and status areas. */
  40. int status_rows = 1;
  41.  
  42. /* These control the layout of edge labels. */
  43. int label_rows;
  44. int label_emcols;
  45.  
  46. /* Temporary hacks for displaying multi-line messages. */
  47. /* If this is non-0, it should be displayed instead of 
  48.  * the windows of cells.  This is a temporary hack.
  49.  * Use set_info to change this.
  50.  */
  51. struct info_buffer * current_info;
  52.  
  53. int info_rows;        /* The height of one row of info in a */
  54.             /* multi-line message. */
  55. int info_line;        /* In the current info buffer, the first vis. line */
  56. int info_over;        /* Info scrolls left/right as well as up/down */
  57.  
  58.  
  59. /* Window borders: */
  60. int default_right_border = 0;
  61. int default_bottom_border = 0;
  62.  
  63. /* The window list. */
  64. int nwin = 0;
  65. struct window *cwin = 0;
  66. struct window *wins = 0;
  67. static int win_id = 1;
  68.  
  69.  
  70. /* Low level window operators. */
  71.  
  72. #define MIN_WIN_HEIGHT(W) (W->bottom_edge_r \
  73.                + label_rows * (W->flags & WIN_EDGES ? 2 : 1))
  74.  
  75. #define MIN_WIN_WIDTH(W) (W->right_edge_c \
  76.               + label_emcols * (W->flags & WIN_EDGES ? 6 : 1))
  77. #define MIN_CWIN_HEIGHT  MIN_WIN_HEIGHT(cwin)
  78. #define MIN_CWIN_WIDTH  MIN_WIN_WIDTH(cwin)
  79.  
  80.  
  81. #ifdef __STDC__
  82. static void 
  83. do_close_window (int num)
  84. #else
  85. static void 
  86. do_close_window (num)
  87.      int num;
  88. #endif
  89. {
  90.   int n;
  91.   struct window *win, *kwin;
  92.   int nlf, nrt, nup, nbl;
  93.   int klo, kho, kld, khd;
  94.   int lo, ho, ld, hd;
  95.   struct tmp
  96.     {
  97.       int l, r, u, b;
  98.     }
  99.    *tmpptr;
  100.  
  101.   if (nwin == 1)
  102.     {
  103.       io_error_msg ("Attempt to delete sole ordinary window.");
  104.       return;
  105.     }
  106.   tmpptr = ck_malloc (sizeof (struct tmp) * nwin);
  107.  
  108.   kwin = &wins[num];
  109.   nlf = nrt = nup = nbl = 0;
  110.   klo = kwin->win_over - kwin->lh_wid;
  111.   kho = kwin->win_over + kwin->numc + kwin->right_edge_c - 1;
  112.   kld = kwin->win_down - (kwin->lh_wid ? label_rows : 0);
  113.   khd = kwin->win_down + kwin->numr + kwin->bottom_edge_r - 1;
  114.  
  115.   for (win = wins; win < &wins[nwin]; win++)
  116.     {
  117.       lo = win->win_over - win->lh_wid;
  118.       ho = win->win_over + win->numc + win->right_edge_c - 1;
  119.       ld = win->win_down - (win->lh_wid ? label_rows : 0);
  120.       hd = win->win_down + win->numr + win->bottom_edge_r - 1;
  121.  
  122.       /* Match to the left ? */
  123.       if (lo == kho + 1)
  124.     {
  125.       if (ld >= kld && hd <= khd)
  126.         tmpptr[nrt++].r = win - wins;
  127.       else if (hd >= kld && ld <= khd)
  128.         nrt = nwin;
  129.     }
  130.       else if (ho == klo - 1)
  131.     {
  132.       if (ld >= kld && hd <= khd)
  133.         tmpptr[nlf++].l = win - wins;
  134.       else if (hd >= kld && ld <= khd)
  135.         nlf = nwin;
  136.     }
  137.       else if (ld == khd + 1)
  138.     {
  139.       if (lo >= klo && ho <= kho)
  140.         tmpptr[nbl++].b = win - wins;
  141.       else if (ho >= kho && lo <= kho)
  142.         nbl = nwin;
  143.     }
  144.       else if (hd == kld - 1)
  145.     {
  146.       if (lo >= klo && ho <= kho)
  147.         tmpptr[nup++].u = win - wins;
  148.       else if (ho >= kho && lo <= kho)
  149.         nup = nwin;
  150.     }
  151.  
  152.     }
  153.   if (nrt == 0)
  154.     nrt = nwin;
  155.   if (nlf == 0)
  156.     nlf = nwin;
  157.   if (nbl == 0)
  158.     nbl = nwin;
  159.   if (nup == 0)
  160.     nup = nwin;
  161.   if (nrt <= nlf && nrt <= nbl && nrt <= nup)
  162.     for (n = 0; n < nrt; n++)
  163.       {
  164.     wins[tmpptr[n].r].numc
  165.       += kwin->lh_wid + kwin->numc + kwin->right_edge_c;
  166.     wins[tmpptr[n].r].win_over
  167.       -= kwin->lh_wid + kwin->numc + kwin->right_edge_c;
  168.       }
  169.   else if (nlf <= nbl && nlf <= nup)
  170.     for (n = 0; n < nlf; n++)
  171.       wins[tmpptr[n].l].numc
  172.     += kwin->lh_wid + kwin->numc + kwin->right_edge_c;
  173.   else if (nbl <= nup)
  174.     for (n = 0; n < nbl; n++)
  175.       {
  176.     wins[tmpptr[n].b].numr
  177.       += kwin->numr + (kwin->lh_wid ? 1 : 0) * label_rows
  178.       + kwin->bottom_edge_r;
  179.  
  180.     wins[tmpptr[n].b].win_down
  181.       -= kwin->numr + (kwin->lh_wid ? 1 : 0) * label_rows
  182.       + kwin->bottom_edge_r;
  183.       }
  184.   else
  185.     for (n = 0; n < nup; n++)
  186.       wins[tmpptr[n].u].numr
  187.     += kwin->numr + (kwin->lh_wid ? 1 : 0) * label_rows;
  188.  
  189.   if (kwin == cwin && kwin != wins)
  190.     --cwin;
  191.   if (cwin == &wins[nwin - 1])
  192.     --cwin;
  193.   while (kwin < &wins[nwin])
  194.     {
  195.       *kwin = kwin[1];
  196.       kwin++;
  197.     }
  198.   --nwin;
  199.   io_recenter_all_win ();
  200.   return;
  201. }
  202.  
  203. #ifdef __STDC__
  204. int
  205. win_label_cols (struct window * win, CELLREF hr)
  206. #else
  207. int
  208. win_label_cols (win, hr)
  209.      struct window * win;
  210.      CELLREF hr;
  211. #endif
  212. {
  213.   int lh;
  214.  
  215.   if ((win->flags & WIN_EDGES) == 0)
  216.     lh = 0;
  217. #if BITS_PER_CELLREF>8
  218.   else if ((win->flags & WIN_PAG_HZ) || hr >= 10000)
  219.     lh = 7;
  220.   else if (hr >= 1000)
  221.     lh = 6;
  222.   else if (hr >= 100)
  223.     lh = 5;
  224. #else
  225.   else if ((win->flags & WIN_PAG_HZ) || hr >= 100)
  226.     lh = 5;
  227. #endif
  228.   else if (hr > 10)
  229.     lh = 4;
  230.   else
  231.     lh = 3;
  232.   lh *= label_emcols;
  233.   return lh;
  234. }
  235.  
  236. #ifdef __STDC__
  237. int
  238. win_label_rows (struct window * win)
  239. #else
  240. int
  241. win_label_rows (win)
  242.      struct window * win;
  243. #endif
  244. {
  245.   return (win->flags & WIN_EDGES) ? label_rows : 0;
  246. }
  247.  
  248. #ifdef __STDC__
  249. static void 
  250. set_numcols (struct window *win, CELLREF hr)
  251. #else
  252. static void 
  253. set_numcols (win, hr)
  254.      struct window *win;
  255.      CELLREF hr;
  256. #endif
  257. {
  258.   int lh = win_label_cols (win, hr);
  259.   win->win_over -= win->lh_wid - lh;
  260.   win->numc += win->lh_wid - lh;
  261.   win->lh_wid = lh;
  262. }
  263.  
  264.  
  265. #ifdef __STDC__
  266. static void 
  267. page_axis (CELLREF cur, int (*get) (CELLREF), int total,
  268.        CELLREF *loP, CELLREF *hiP)
  269. #else
  270. static void 
  271. page_axis (cur, get, total, loP, hiP)
  272.      CELLREF cur;
  273.      int (*get) ();
  274.      int total;
  275.      CELLREF *loP;
  276.      CELLREF *hiP;
  277. #endif
  278. {
  279.   CELLREF lo, hi;
  280.   int w, ww;
  281.  
  282.   lo = hi = MIN_ROW;
  283.   w = (*get) (hi);
  284.   for (;;)
  285.     {
  286.       ww = (*get) (hi + 1);
  287.       while (w + ww <= total && hi < MAX_ROW)
  288.     {
  289.       hi++;
  290.       w += ww;
  291.       ww = (*get) (hi + 1);
  292.     }
  293.       if (hi >= cur)
  294.     break;
  295.       hi++;
  296.       lo = hi;
  297.       w = ww;
  298.     }
  299.   if (lo > cur || hi > MAX_ROW)
  300.     io_error_msg ("Can't find a non-zero-sized cell page_axis");
  301.   *loP = lo;
  302.   *hiP = hi;
  303. }
  304.  
  305.  
  306. #ifdef __STDC__
  307. static void 
  308. recenter_axis (CELLREF cur, int (*get) (CELLREF), int total,
  309.            CELLREF *loP, CELLREF *hiP)
  310. #else
  311. static void 
  312. recenter_axis (cur, get, total, loP, hiP)
  313.      CELLREF cur;
  314.      int (*get) ();
  315.      int total;
  316.      CELLREF *loP;
  317.      CELLREF *hiP;
  318. #endif
  319. {
  320.   CELLREF lo, hi;
  321.   int tot;
  322.   int n;
  323.   int more;
  324.  
  325.   lo = hi = cur;
  326.   n = tot = (*get) (cur);
  327.   do
  328.     {
  329.       if (lo > MIN_ROW && tot + (n = (*get) (lo - 1)) <= total)
  330.     {
  331.       --lo;
  332.       tot += n;
  333.       more = 1;
  334.     }
  335.       else
  336.     more = 0;
  337.       if (hi < MAX_ROW && tot + (n = (*get) (hi + 1)) <= total)
  338.     {
  339.       hi++;
  340.       tot += n;
  341.       more++;
  342.     }
  343.     }
  344.   while (more);
  345.   *loP = lo;
  346.   *hiP = hi;
  347. }
  348.  
  349. #ifdef __STDC__
  350. static void 
  351. recenter_window (struct window *win)
  352. #else
  353. static void 
  354. recenter_window (win)
  355.      struct window *win;
  356. #endif
  357. {
  358.   if (win->flags & WIN_PAG_VT)
  359.     page_axis (win->win_curow, get_scaled_height, win->numr,
  360.            &(win->screen.lr), &(win->screen.hr));
  361.   else
  362.     recenter_axis (win->win_curow, get_scaled_height, win->numr,
  363.            &(win->screen.lr), &(win->screen.hr));
  364.   set_numcols (win, win->screen.hr);
  365.   if (win->flags & WIN_PAG_HZ)
  366.     page_axis (win->win_cucol, get_scaled_width, win->numc,
  367.            &(win->screen.lc), &(win->screen.hc));
  368.   else
  369.     recenter_axis (win->win_cucol, get_scaled_width, win->numc,
  370.            &(win->screen.lc), &(win->screen.hc));
  371. }
  372.  
  373.  
  374. /*
  375.  * RESIZE_SCREEN adjusts the windows list after a screen size change.
  376.  * It presumes that LINES and COLS are the new values.  DR and DC
  377.  * are the changes that just occured to those values.
  378.  */
  379. #ifdef __STDC__
  380. static void 
  381. resize_screen (int dr, int dc)
  382. #else
  383. static void 
  384. resize_screen (dr, dc)
  385.      int dr;
  386.      int dc;
  387. #endif
  388. {
  389.   int x, n;
  390.   int lines;
  391.   int firstln;
  392.   int ncols;
  393.   int firstcol;
  394.   int old_lines;
  395.  
  396.   if (!nwin)
  397.     return;
  398.  
  399.   lines = scr_lines - (!!user_status * status_rows) - input_rows;
  400.   old_lines = lines - dr;
  401.   firstln = (user_input > 0) * input_rows + (user_status > 0) * status_rows;
  402.  
  403.   /* First, delete windows that will shrink too much. */
  404.   cwin->win_curow = curow;
  405.   cwin->win_cucol = cucol;
  406.   if (dr < 0)
  407.     for (x = 0; x < nwin; x++)
  408.       {
  409.     int rlow =
  410.     (wins[x].win_down - (wins[x].lh_wid ? label_rows : 0) - firstln);
  411.     int rhi = ((wins[x].win_down + wins[x].numr + wins[x].bottom_edge_r)
  412.            - firstln);
  413.     int sqbelow = dr * rlow;
  414.     int sqtohere = dr * rhi;
  415.     sqbelow /= old_lines;
  416.     sqtohere /= old_lines;
  417.     if (wins[x].numr <= sqbelow - sqtohere)
  418.       {
  419.         do_close_window (x);
  420.         x--;
  421.       }
  422.       }
  423.   for (x = 0; x < nwin; ++x)
  424.     {
  425.       int rlow =
  426.       (wins[x].win_down - (wins[x].lh_wid ? label_rows : 0) - firstln);
  427.       int rhi = ((wins[x].win_down + wins[x].numr + wins[x].bottom_edge_r)
  428.          - firstln);
  429.       int sqbelow = dr * rlow;
  430.       int sqtohere = dr * rhi;
  431.       sqbelow /= old_lines;
  432.       sqtohere /= old_lines;
  433.       wins[x].win_down += sqbelow;
  434.       wins[x].numr += sqtohere - sqbelow;
  435.     }
  436.  
  437.   /* then columns */
  438.   firstcol = 0;
  439.   ncols = COLS;
  440.   ncols -= dc;
  441.  
  442.   /* First, delete windows that will shrink too much. */
  443.   if (dc < 0)
  444.     for (x = 0; x < nwin; x++)
  445.       {
  446.     int clow = (wins[x].win_over - wins[x].lh_wid) - firstcol;
  447.     int chi = (wins[x].win_over + wins[x].numc + wins[x].right_edge_c
  448.            - firstcol);
  449.     int sqbelow = dc * clow;
  450.     int sqtohere = dc * chi;
  451.     sqbelow /= ncols;
  452.     sqtohere /= ncols;
  453.     if (wins[x].numc <= sqbelow - sqtohere)
  454.       {
  455.         do_close_window (x);
  456.         x--;
  457.       }
  458.       }
  459.   for (x = 0; x < nwin; ++x)
  460.     {
  461.       int clow = (wins[x].win_over - wins[x].lh_wid) - firstcol;
  462.       int chi = (wins[x].win_over + wins[x].numc + wins[x].right_edge_c
  463.          - firstcol);
  464.       int sqbelow = dc * clow;
  465.       int sqtohere = dc * chi;
  466.       sqbelow /= ncols;
  467.       sqtohere /= ncols;
  468.       wins[x].win_over += sqbelow;
  469.       wins[x].numc += sqtohere - sqbelow;
  470.     }
  471.   for (n = 0; n < nwin; n++)
  472.     recenter_window (&wins[n]);
  473.   io_repaint ();
  474. }
  475.  
  476. #ifdef __STDC__
  477. static void
  478. shift_linked_window (long dn, long ov)
  479. #else
  480. static void
  481. shift_linked_window (dn, ov)
  482.      long dn;
  483.      long ov;
  484. #endif
  485. {
  486.   struct window *win;
  487.  
  488.   win = cwin;
  489.   while (win->link != -1)
  490.     {
  491.       win = &wins[win->link];
  492.       if (win == cwin)        /* Loop check! */
  493.     return;
  494.       if ((win->flags & WIN_LCK_VT) == 0)
  495.     win->win_curow += dn;
  496.       if ((win->flags & WIN_LCK_HZ) == 0)
  497.     win->win_cucol += ov;
  498.       if (win->win_curow < win->screen.lr || win->win_curow > win->screen.hr
  499.       || win->win_cucol < win->screen.lc || win->win_cucol > win->screen.hc)
  500.     recenter_window (win);
  501.     }
  502. }
  503.  
  504.  
  505. #ifdef __STDC__
  506. static void 
  507. find_nonzero (CELLREF *curp, CELLREF lo, CELLREF hi,
  508.           int (*get) (CELLREF))
  509. #else
  510. static void 
  511. find_nonzero (curp, lo, hi, get)
  512.      CELLREF *curp;
  513.      CELLREF lo;
  514.      CELLREF hi;
  515.      int (*get) ();
  516. #endif
  517. {
  518.   CELLREF cc;
  519.   int n;
  520.  
  521.   cc = *curp;
  522.  
  523.   if (cc < hi)
  524.     {
  525.       cc++;
  526.       while ((n = (*get) (cc)) == 0)
  527.     {
  528.       if (cc == hi)
  529.         break;
  530.       cc++;
  531.     }
  532.       if (n)
  533.     {
  534.       *curp = cc;
  535.       return;
  536.     }
  537.     }
  538.   if (cc > lo)
  539.     {
  540.       --cc;
  541.       while ((n = (*get) (cc)) == 0)
  542.     {
  543.       if (cc == lo)
  544.         break;
  545.       --cc;
  546.     }
  547.       if (n)
  548.     {
  549.       *curp = cc;
  550.       return;
  551.     }
  552.     }
  553. }
  554.  
  555. #ifdef __STDC__
  556. static int 
  557. scroll_axis (CELLREF cur, int over, int total, int (*get) (CELLREF),
  558.          CELLREF *ret1, CELLREF *ret2, int *offp) 
  559. #else
  560. static int 
  561. scroll_axis (cur, over, total, get, ret1, ret2, offp)
  562.      CELLREF cur;
  563.      int over;
  564.      int total;
  565.      int (*get) ();
  566.      CELLREF *ret1;
  567.      CELLREF *ret2;
  568.      int *offp;
  569. #endif
  570. {
  571.   int tot; 
  572.  
  573.   int inc;
  574.   CELLREF fini;
  575.   int num;
  576.   CELLREF p1, p2;
  577.   int n;
  578.  
  579.   inc = (over > 0 ? 1 : -1);
  580.   fini = over > 0 ? MAX_ROW : MIN_ROW;
  581.   num = over > 0 ? over : -over;
  582.  
  583.   if (inc > 0 ? *ret2 == MAX_ROW : *ret1 == MIN_ROW)
  584.     return 1;
  585.   p1 = inc > 0 ? *ret2 + 1 : *ret1 - 1;
  586.   p2 = p1;
  587.   for (;;)
  588.     {
  589.       --num;
  590.       tot = (*get) (p1);
  591.       while (p2 != fini && tot + (n = (*get) (p2 + inc)) <= total)
  592.     {
  593.       p2 += inc;
  594.       tot += n;
  595.     }
  596.       if (!num || p2 == fini)
  597.     break;
  598.     }
  599.   if (num)
  600.     return 1;
  601.   while (tot + (n = (*get) (p1 - inc)) <= total)
  602.     {
  603.       p1 -= inc;
  604.       tot += n;
  605.       if (inc > 0)
  606.     (*offp)++;
  607.     }
  608.   if (p1 > p2)
  609.     {
  610.       *ret1 = p2;
  611.       *ret2 = p1;
  612.     }
  613.   else
  614.     {
  615.       *ret1 = p1;
  616.       *ret2 = p2;
  617.     }
  618.   return 0;
  619. }
  620.  
  621. #ifdef __STDC__
  622. static int 
  623. page_scroll_axis (CELLREF cur, int over, int total, int (*get) (CELLREF),
  624.           CELLREF *ret1, CELLREF *ret2, int *offp)
  625. #else
  626. static int 
  627. page_scroll_axis (cur, over, total, get, ret1, ret2, offp)
  628.      CELLREF cur;
  629.      int over;
  630.      int total;
  631.      int (*get) ();
  632.      CELLREF *ret1;
  633.      CELLREF *ret2;
  634.      int *offp;
  635. #endif
  636. {
  637.   int n_over;
  638.   CELLREF lo, hi;
  639.   int tot;
  640.   int ww;
  641.  
  642.   n_over = 0;
  643.   lo = hi = MIN_ROW;
  644.   tot = (*get) (hi);
  645.   for (;;)
  646.     {
  647.       while (hi < MAX_ROW && tot + (ww = (*get) (hi + 1)) <= total)
  648.     {
  649.       hi++;
  650.       tot += ww;
  651.     }
  652.       if (hi >= cur)
  653.     break;
  654.       hi++;
  655.       n_over++;
  656.       lo = hi;
  657.       tot = ww;
  658.     }
  659.   n_over += over;
  660.   if (n_over < 0)
  661.     return 1;
  662.  
  663.   lo = hi = MIN_ROW;
  664.   tot = (*get) (hi);
  665.   for (;;)
  666.     {
  667.       while (hi < MAX_ROW && tot + (ww = (*get) (hi + 1)) <= total)
  668.     {
  669.       hi++;
  670.       tot += ww;
  671.     }
  672.       if (!n_over || hi == MAX_ROW)
  673.     break;
  674.       --n_over;
  675.       hi++;
  676.       lo = hi;
  677.       tot = ww;
  678.     }
  679.   if (hi == MAX_ROW && n_over)
  680.     return 1;
  681.   *ret1 = lo;
  682.   *ret2 = hi;
  683.   return 0;
  684. }
  685.  
  686.  
  687.  
  688. /* External window interface */
  689.  
  690. #ifdef __STDC__
  691. void 
  692. io_set_label_size (int r, int c)
  693. #else
  694. void 
  695. io_set_label_size (r, c)
  696.      int r;
  697.      int c;
  698. #endif
  699. {
  700.   /* fixme */
  701. }
  702.  
  703. #ifdef __STDC__
  704. void 
  705. io_set_scr_size (int lines, int cols)
  706. #else
  707. void 
  708. io_set_scr_size (lines, cols)
  709.      int lines;
  710.      int cols;
  711. #endif
  712. {
  713.   int dl = lines - scr_lines;
  714.   int dc = cols - scr_cols;
  715.  
  716.   scr_lines = lines;
  717.   scr_cols = cols;
  718.  
  719.   resize_screen (dl, dc);
  720. }
  721.  
  722. #ifdef __STDC__
  723. void 
  724. io_set_input_rows (int n)
  725. #else
  726. void 
  727. io_set_input_rows (n)
  728.      int n;
  729. #endif
  730. {
  731.   input_rows = n;
  732.   io_set_input_status (user_input, user_status, 1);
  733. }
  734.  
  735. #ifdef __STDC__
  736. void 
  737. io_set_status_rows (int n)
  738. #else
  739. void 
  740. io_set_status_rows (n)
  741.      int n;
  742. #endif
  743. {
  744.   status_rows = n;
  745.   io_set_input_status (user_input, user_status, 1);
  746. }
  747.  
  748. #ifdef __STDC__
  749. void 
  750. io_set_input_status (int inp, int stat, int redraw)
  751. #else
  752. void 
  753. io_set_input_status (inp, stat, redraw)
  754.      int inp;
  755.      int stat;
  756.      int redraw;
  757. #endif
  758. {
  759.   int inpv = inp < 0 ? -inp : inp;
  760.   int inpsgn = inp == inpv ? 1 : -1;
  761.   int statv = stat < 0 ? -stat : stat;
  762.   int statsgn = stat == statv ? 1 : -1;
  763.   int new_ui;
  764.   int new_us;
  765.   int new_inp;
  766.   int new_stat;
  767.  
  768.   if (inpv == 0 || inpv > 2)
  769.     io_error_msg ("Bad input location %d; it should be +/- 1, or 2", inp);
  770.   else if (statv > 2)
  771.     io_error_msg ("Bad status location %d; it should be +/- 0, 1, or 2",
  772.           inp);
  773.   else
  774.     {
  775.       new_ui = inp;
  776.       new_us = stat;
  777.       if (inpsgn != statsgn)
  778.     if (inpsgn > 0)
  779.       {
  780.         new_inp = 0;
  781.         new_stat = LINES - status_rows;
  782.       }
  783.     else
  784.       {
  785.         new_inp = LINES - input_rows;
  786.         new_stat = 0;
  787.       }
  788.       else
  789.     {
  790.       if (inpv > statv)
  791.         {
  792.           new_inp = new_us ? status_rows : 0;
  793.           new_stat = 0;
  794.         }
  795.       else
  796.         {
  797.           new_inp = 0;
  798.           new_stat = input_rows;
  799.         }
  800.       if (inpsgn < 0)
  801.         {
  802.           new_stat = LINES - new_stat - status_rows;
  803.           new_inp = LINES - new_inp - input_rows;
  804.         }
  805.     }
  806.       if (redraw)
  807.     {
  808.       int vchange =
  809.       (((new_ui > 0 ? input_rows : 0)
  810.         + (new_us > 0 ? status_rows : 0))
  811.        - ((user_input > 0 ? input_rows : 0)
  812.           + (user_status > 0 ? status_rows : 0)));
  813.       int grow = (user_status
  814.               ? (new_us ? 0 : status_rows)
  815.               : (new_us ? -status_rows : 0));
  816.       int cell_top =
  817.       ((user_status > 0 ? status_rows : 0)
  818.        + (user_input > 0 ? input_rows : 0));
  819.  
  820.       if (grow < 0)
  821.         {
  822.           int x;
  823.         re:
  824.           for (x = 0; x < nwin; ++x)
  825.         {
  826.           int top = wins[x].win_down - win_label_rows(&wins[x]);
  827.           if (cell_top == top && (wins[x].numr <= -grow))
  828.             {
  829.               do_close_window (x);
  830.               goto re;
  831.             }
  832.         }
  833.         }
  834.  
  835.       if (grow)
  836.         {
  837.           int x;
  838.           for (x = 0; x < nwin; ++x)
  839.         {
  840.           int top =
  841.           wins[x].win_down - win_label_rows (&wins[x]);
  842.           if (cell_top == top)
  843.             wins[x].numr -= vchange;
  844.         }
  845.         }
  846.       if (vchange)
  847.         {
  848.           int x;
  849.           for (x = 0; x < nwin; ++x)
  850.         wins[x].win_down += vchange;
  851.         }
  852.       io_repaint ();
  853.     }
  854.       user_input = new_ui;
  855.       user_status = new_us;
  856.       input = new_inp;
  857.       status = new_stat;
  858.     }
  859. }
  860.  
  861. #ifdef __STDC__
  862. void 
  863. io_set_cwin (struct window *win)
  864. #else
  865. void 
  866. io_set_cwin (win)
  867.      struct window *win;
  868. #endif
  869. {
  870.   io_hide_cell_cursor ();
  871.   cwin->win_curow = curow;
  872.   cwin->win_cucol = cucol;
  873.   cwin = win;
  874.   curow = cwin->win_curow;
  875.   cucol = cwin->win_cucol;
  876.   io_display_cell_cursor ();
  877. }
  878.  
  879.  
  880. #ifdef __STDC__
  881. void 
  882. io_pr_cell (CELLREF r, CELLREF c, CELL *cp)
  883. #else
  884. void 
  885. io_pr_cell (r, c, cp)
  886.      CELLREF r;
  887.      CELLREF c;
  888.      CELL *cp;
  889. #endif
  890. {
  891.   struct window *win;
  892.  
  893.   for (win = wins; win < &wins[nwin]; win++)
  894.     {
  895.       if (r < win->screen.lr || r > win->screen.hr
  896.       || c < win->screen.lc || c > win->screen.hc)
  897.     continue;
  898.       io_pr_cell_win (win, r, c, cp);
  899.     }
  900. }
  901.  
  902. #ifdef __STDC__
  903. void
  904. io_redo_region (struct rng * rng)
  905. #else
  906. void
  907. io_redo_region (rng)
  908.      struct rng * rng;
  909. #endif
  910. {
  911.   CELL * cp;
  912.   CELLREF r, c;
  913.   find_cells_in_range (rng);
  914.   cp = next_row_col_in_range (&r, &c);
  915.   while (cp)
  916.     {
  917.       io_pr_cell (r, c, cp);
  918.       cp = next_row_col_in_range (&r, &c);
  919.     }
  920. }
  921.  
  922. /* Create a new window by splitting the current one. */
  923. #ifdef __STDC__
  924. void 
  925. io_win_open (int hv, int where)
  926. #else
  927. void 
  928. io_win_open (hv, where)
  929.      int hv;
  930.      int where;
  931. #endif
  932. {
  933.   int tmp;
  934.   struct window *win;
  935.  
  936.   if (   (!hv
  937.       && (where < MIN_CWIN_WIDTH
  938.           || (cwin->numc + cwin->lh_wid + cwin->right_edge_c - where
  939.                < MIN_CWIN_WIDTH)))
  940.       || (hv
  941.       && (where < MIN_CWIN_HEIGHT
  942.           || (cwin->numr + cwin->bottom_edge_r
  943.           + (cwin->lh_wid ? label_rows : 0) - where
  944.           < MIN_CWIN_HEIGHT))))
  945.     {
  946.       io_error_msg ("Window won't fit!");
  947.       return;
  948.     }
  949.  
  950.   nwin++;
  951.   tmp = cwin - wins;
  952.   wins = ck_realloc (wins, nwin * sizeof (struct window));
  953.   win = &wins[nwin - 1];
  954.   cwin = &wins[tmp];
  955.   win->id = win_id++;
  956.   win->bottom_edge_r = cwin->bottom_edge_r;
  957.   win->right_edge_c = cwin->right_edge_c;
  958.   /* set_numcols will take care of fixing win_over if edges are on. */
  959.   win->win_over = cwin->win_over + (hv ? 0 : where) - cwin->lh_wid;
  960.   win->win_down = cwin->win_down + (hv ? where : 0);
  961.   win->flags = cwin->flags;
  962.   win->link = -1;
  963.   win->lh_wid = 0;
  964.   win->win_slops = 0;
  965.   win->numc = cwin->numc + cwin->lh_wid + (hv ? 0 : -where);
  966.   win->numr = cwin->numr + (hv ? -where : 0);
  967.   win->win_curow = curow;
  968.   win->win_cucol = cucol;
  969.   set_numcols (win, curow);
  970.   cwin->numc -= (hv ? 0 : win->numc + win->lh_wid + win->right_edge_c);
  971.   cwin->numr -=
  972.     (hv ? win->numr + (win->lh_wid ? label_rows : 0) + win->bottom_edge_r
  973.      : 0);
  974.   cwin->win_curow = curow;
  975.   cwin->win_cucol = cucol;
  976.   io_hide_cell_cursor ();
  977.   win = cwin;
  978.   cwin = &wins[nwin - 1];
  979.   recenter_window (cwin);
  980.   recenter_window (win);
  981.   io_display_cell_cursor ();
  982.   io_repaint ();
  983. }
  984.  
  985. #ifdef __STDC__
  986. void 
  987. io_win_close (struct window *win)
  988. #else
  989. void 
  990. io_win_close (win)
  991.      struct window *win;
  992. #endif
  993. {
  994.   do_close_window (win - wins);
  995. }
  996.  
  997. #ifdef __STDC__
  998. void 
  999. io_move_cell_cursor (CELLREF rr, CELLREF cc)
  1000. #else
  1001. void 
  1002. io_move_cell_cursor (rr, cc)
  1003.      CELLREF rr;
  1004.      CELLREF cc;
  1005. #endif
  1006. {
  1007.   if (cwin->link != -1)
  1008.     shift_linked_window ((long) rr - curow, (long) cc - cucol);
  1009.   if (rr < cwin->screen.lr || rr > cwin->screen.hr
  1010.       || cc < cwin->screen.lc || cc > cwin->screen.hc)
  1011.     {
  1012.       cwin->win_curow = curow = rr;
  1013.       cwin->win_cucol = cucol = cc;
  1014.       recenter_window (cwin);
  1015.       io_repaint_win (cwin);
  1016.       if (cwin->link > 0)
  1017.     io_repaint_win (&wins[cwin->link]);
  1018.     }
  1019.   else
  1020.     {
  1021.       io_hide_cell_cursor ();
  1022.       curow = rr;
  1023.       cucol = cc;
  1024.       io_display_cell_cursor ();
  1025.       io_update_status ();
  1026.     }
  1027.   if (get_scaled_width (cucol) == 0)
  1028.     find_nonzero (&cucol, cwin->screen.lc, cwin->screen.hc, get_scaled_width);
  1029.   if (get_scaled_height (curow) == 0)
  1030.     find_nonzero (&curow, cwin->screen.lr, cwin->screen.hr, get_scaled_height);
  1031. }
  1032.  
  1033. #ifdef __STDC__
  1034. void 
  1035. io_shift_cell_cursor (int dirn, int repeat)
  1036. #else
  1037. void 
  1038. io_shift_cell_cursor (dirn, repeat)
  1039.      int dirn;
  1040.      int repeat;
  1041. #endif
  1042. {
  1043.   CELLREF c;
  1044.   CELLREF r;
  1045.   int w = 0;
  1046.   int over, down;
  1047.  
  1048.   over = colmagic[dirn] * repeat;
  1049.   down = rowmagic[dirn] * repeat;
  1050.   if (over > 0)
  1051.     {
  1052.       c = cucol;
  1053.       while (c < MAX_COL && over-- > 0)
  1054.     {
  1055.       c++;
  1056.       while ((w = get_scaled_width (c)) == 0 && c < MAX_COL)
  1057.         c++;
  1058.     }
  1059.       if (over > 0 || c == cucol || w == 0)
  1060.     {
  1061.       io_error_msg ("Can't go right");
  1062.       return;
  1063.     }
  1064.     }
  1065.   else if (over < 0)
  1066.     {
  1067.       c = cucol;
  1068.       while (c > MIN_COL && over++ < 0)
  1069.     {
  1070.       --c;
  1071.       while ((w = get_scaled_width (c)) == 0 && c > MIN_COL)
  1072.         --c;
  1073.     }
  1074.       if (over < 0 || c == cucol || w == 0)
  1075.     {
  1076.       io_error_msg ("Can't go left");
  1077.       return;
  1078.     }
  1079.     }
  1080.   else
  1081.     c = cucol;
  1082.  
  1083.   if (down > 0)
  1084.     {
  1085.       r = curow;
  1086.       while (r < MAX_ROW && down-- > 0)
  1087.     {
  1088.       r++;
  1089.       while ((w = get_scaled_height (r)) == 0 && r < MAX_ROW)
  1090.         r++;
  1091.     }
  1092.       if (down > 0 || r == curow || w == 0)
  1093.     {
  1094.       io_error_msg ("Can't go down");
  1095.       return;
  1096.     }
  1097.     }
  1098.   else if (down < 0)
  1099.     {
  1100.       r = curow;
  1101.       while (r > MIN_ROW && down++ < 0)
  1102.     {
  1103.       --r;
  1104.       while ((w = get_scaled_height (r)) == 0 && r > MIN_ROW)
  1105.         --r;
  1106.     }
  1107.       if (down < 0 || r == curow || w == 0)
  1108.     {
  1109.       io_error_msg ("Can't go up");
  1110.       return;
  1111.     }
  1112.     }
  1113.   else
  1114.     r = curow;
  1115.  
  1116.   io_move_cell_cursor (r, c);
  1117. }
  1118.  
  1119. #ifdef __STDC__
  1120. void 
  1121. io_scroll_cell_cursor (int magic, int repeat)
  1122. #else
  1123. void 
  1124. io_scroll_cell_cursor (magic, repeat)
  1125.      int magic;
  1126.      int repeat;
  1127. #endif
  1128. {
  1129.   int off_dn, off_rt;
  1130.  
  1131.   struct rng s;
  1132.   CELLREF cr, cc;
  1133.   int over, down;
  1134.   int ret;
  1135.  
  1136.   over = colmagic[magic];
  1137.   down = rowmagic[magic];
  1138.  
  1139.   s.lr = cwin->screen.lr;
  1140.   s.hr = cwin->screen.hr;
  1141.   if (down)
  1142.     {
  1143.       off_dn = curow - cwin->screen.lr;
  1144.       if (cwin->flags & WIN_PAG_VT)
  1145.     ret = page_scroll_axis
  1146.       (curow, down, cwin->numr, get_scaled_height, &(s.lr), &(s.hr), &off_dn);
  1147.       else
  1148.     ret = scroll_axis
  1149.       (curow, down, cwin->numr, get_scaled_height, &(s.lr), &(s.hr), &off_dn);
  1150.       cr = (off_dn > s.hr - s.lr) ? s.hr : s.lr + off_dn;
  1151.       if (ret)
  1152.     io_error_msg ("Can't scroll that far");
  1153.       set_numcols (cwin, s.hr);
  1154.     }
  1155.   else
  1156.     cr = curow;
  1157.  
  1158.   off_rt = cucol - cwin->screen.lc;
  1159.  
  1160.   s.lc = cwin->screen.lc;
  1161.   s.hc = cwin->screen.hc;
  1162.   if (over)
  1163.     {
  1164.       if (cwin->flags & WIN_PAG_HZ)
  1165.     ret = page_scroll_axis
  1166.       (cucol, over, cwin->numc, get_scaled_width, &(s.lc), &(s.hc), &off_rt);
  1167.       else
  1168.     ret = scroll_axis (cucol, over, cwin->numc, get_scaled_width, &(s.lc), &(s.hc), &off_rt);
  1169.       if (ret)
  1170.     io_error_msg ("Can't scroll that far");
  1171.       cc = (s.hc - s.lc < off_rt) ? s.hc : s.lc + off_rt;
  1172.     }
  1173.   else if ((cwin->flags & WIN_PAG_HZ) == 0)
  1174.     /* ... */
  1175.     cc = cucol;
  1176.   else
  1177.     cc = cucol;
  1178.  
  1179.   /*fixme The original has a big #if 0 here. */
  1180.   if (cwin->link != -1)
  1181.     shift_linked_window ((long) cr - curow, (long) cc - cucol);
  1182.  
  1183.   cwin->screen = s;
  1184.   curow = cr;
  1185.   cucol = cc;
  1186.  
  1187.   if (get_scaled_width (cucol) == 0)
  1188.     find_nonzero (&cucol, cwin->screen.lc, cwin->screen.hc, get_scaled_width);
  1189.   if (get_scaled_height (curow) == 0)
  1190.     find_nonzero (&curow, cwin->screen.lr, cwin->screen.hr, get_scaled_height);
  1191.  
  1192.   io_repaint_win (cwin);
  1193.   if (cwin->link > 0)
  1194.     io_repaint_win (&wins[cwin->link]);
  1195. }
  1196.  
  1197. #ifdef __STDC__
  1198. void 
  1199. io_recenter_cur_win (void)
  1200. #else
  1201. void 
  1202. io_recenter_cur_win ()
  1203. #endif
  1204. {
  1205.   cwin->win_curow = curow;
  1206.   cwin->win_cucol = cucol;
  1207.   recenter_window (cwin);
  1208.   io_repaint_win (cwin);
  1209.   if (cwin->link > 0)
  1210.     io_repaint_win (&wins[cwin->link]);
  1211. }
  1212.  
  1213. #ifdef __STDC__
  1214. void 
  1215. io_recenter_all_win (void)
  1216. #else
  1217. void 
  1218. io_recenter_all_win ()
  1219. #endif
  1220. {
  1221.   int n;
  1222.   if (!nwin)
  1223.     return;
  1224.   cwin->win_curow = curow;
  1225.   cwin->win_cucol = cucol;
  1226.   for (n = 0; n < nwin; n++)
  1227.     recenter_window (&wins[n]);
  1228.   io_repaint ();
  1229. }
  1230.  
  1231. #ifdef __STDC__
  1232. void 
  1233. io_set_win_flags (struct window *w, int f)
  1234. #else
  1235. void 
  1236. io_set_win_flags (w, f)
  1237.      struct window *w;
  1238.      int f;
  1239. #endif
  1240. {
  1241.   if ((f & WIN_EDGES) && !(w->flags & WIN_EDGES))
  1242.     {
  1243.       if (w->numr < 2 || w->numc < 6)
  1244.     io_error_msg ("Edges wouldn't fit!");
  1245.       w->win_down++;
  1246.       w->numr--;
  1247.       set_numcols (w, w->screen.hr);
  1248.     }
  1249.   else if (!(f & WIN_EDGES) && (w->flags & WIN_EDGES))
  1250.     {
  1251.       w->win_over -= w->lh_wid;
  1252.       w->numc += w->lh_wid;
  1253.       w->lh_wid = 0;
  1254.       w->win_down--;
  1255.       w->numr++;
  1256.     }
  1257.   w->flags = f;
  1258. }
  1259.  
  1260. #ifdef __STDC__
  1261. void 
  1262. io_write_window_config (struct line * out)
  1263. #else
  1264. void 
  1265. io_write_window_config (out)
  1266.      struct line *out;
  1267. #endif
  1268. {
  1269.   int n;
  1270.   char buf[90];
  1271.   struct line scratch;
  1272.   scratch.alloc = 0;
  1273.   scratch.buf = 0;
  1274.  
  1275.   cwin->win_curow = curow;
  1276.   cwin->win_cucol = cucol;
  1277.   sprint_line (out, "O;status %d\n", user_status);
  1278.   if (nwin > 1)
  1279.     {
  1280.       /* ... *//* fixme ? */
  1281.     }
  1282.   for (n = 0; n < nwin; n++)
  1283.     {
  1284.       buf[0] = '\0';
  1285.       if (wins[n].flags & WIN_LCK_HZ)
  1286.     strcat (buf, ",lockh");
  1287.       if (wins[n].flags & WIN_LCK_VT)
  1288.     strcat (buf, ",lockv");
  1289.       if (wins[n].flags & WIN_PAG_HZ)
  1290.     strcat (buf, ",pageh");
  1291.       if (wins[n].flags & WIN_PAG_VT)
  1292.     strcat (buf, ",pagev");
  1293.       if (wins[n].flags & WIN_EDGE_REV)
  1294.     strcat (buf, ",standout");
  1295.       if ((wins[n].flags & WIN_EDGES) == 0)
  1296.     strcat (buf, ",noedges");
  1297.       scratch = *out;
  1298.       out->alloc = 0;
  1299.       out->buf = 0;
  1300.       sprint_line (out, "%sW;N%d;A%u %u;C%d %d %d;O%s\n",
  1301.            scratch.buf, n + 1, wins[n].win_curow, wins[n].win_cucol,
  1302.            7, 0, 7, buf + 1);
  1303.       free (scratch.buf);
  1304.     }
  1305. }
  1306.  
  1307. #ifdef __STDC__
  1308. void 
  1309. io_read_window_config (char * line)
  1310. #else
  1311. void 
  1312. io_read_window_config (line)
  1313.      char *line;
  1314. #endif
  1315. {
  1316.   int wnum = 0;
  1317.   char *text;
  1318.   CELLREF nrow = NON_ROW, ncol = NON_COL;
  1319.   char *split = 0;
  1320.   char *opts = 0;
  1321.   struct window *win;
  1322.  
  1323.   text = line;
  1324.   for (;;)
  1325.     {
  1326.       switch (*text++)
  1327.     {
  1328.       /* Window Number */
  1329.     case 'N':
  1330.       wnum = astol (&text);
  1331.       break;
  1332.       /* Cursor At */
  1333.     case 'A':
  1334.       nrow = astol (&text);
  1335.       ncol = astol (&text);
  1336.       break;
  1337.       /* JF: Window options */
  1338.     case 'O':
  1339.       opts = text;
  1340.       while (*text && *text != ';')
  1341.         text++;
  1342.       break;
  1343.       /* Split into two windows */
  1344.     case 'S':
  1345.       split = text;
  1346.       while (*text && *text != ';')
  1347.         text++;
  1348.       break;
  1349.       /* Set Colors NOT supported */
  1350.     case 'C':
  1351.       while (*text && *text != ';')
  1352.         text++;
  1353.       break;
  1354.       /* Alternate border NOT supported. . . */
  1355.     case 'B':
  1356.       break;
  1357.     default:
  1358.       --text;
  1359.       break;
  1360.     }
  1361.       if (*text == '\0' || *text == '\n')
  1362.     break;
  1363.       if (*text != ';')
  1364.     {
  1365.       char *bad;
  1366.  
  1367.       bad = text;
  1368.       while (*text && *text != ';')
  1369.         text++;
  1370.       if (*text)
  1371.         *text++ = '\0';
  1372.       io_error_msg ("Unknown SYLK window cmd: %s", bad);
  1373.       if (!*text)
  1374.         break;
  1375.     }
  1376.       else
  1377.     *text++ = '\0';
  1378.     }
  1379.   if (wnum < 1 || wnum > nwin)
  1380.     {
  1381.       io_error_msg ("Window %d out of range in SYLK line %s", wnum, line);
  1382.       return;
  1383.     }
  1384.   --wnum;
  1385.   win = &wins[wnum];
  1386.   if (nrow != NON_ROW)
  1387.     {
  1388.       win->win_curow = nrow;
  1389.       win->win_cucol = ncol;
  1390.       if (win == cwin)
  1391.     {
  1392.       curow = nrow;
  1393.       cucol = ncol;
  1394.     }
  1395.       recenter_window (win);
  1396.     }
  1397.   if (split)
  1398.     {
  1399.       int hv = 0;
  1400.       int where;
  1401.       int link;
  1402.       struct window *new;
  1403.  
  1404.       switch (*split++)
  1405.     {
  1406.     case 'H':
  1407.     case 'h':
  1408.       hv = 1;
  1409.       break;
  1410.     case 'v':
  1411.     case 'V':
  1412.       hv = 0;
  1413.       break;
  1414.     case 't':
  1415.     case 'T':
  1416.       io_error_msg ("Window split titles not supported");
  1417.       return;
  1418.     default:
  1419.       break;
  1420.     }
  1421.       if (*split == 'L')
  1422.     {
  1423.       link = wnum;
  1424.       split++;
  1425.     }
  1426.       else
  1427.     link = -1;
  1428.  
  1429.       where = astol (&split);
  1430.  
  1431.       if (hv ? where >= win->numr : where >= win->numc)
  1432.     io_error_msg ("Can't split window: screen too small");
  1433.  
  1434.       nwin++;
  1435.       wins = ck_realloc (wins, nwin * sizeof (struct window));
  1436.       cwin = wins;
  1437.       win = &wins[wnum];
  1438.       new = &wins[nwin - 1];
  1439.  
  1440.       win->numc -= (hv ? 0 : where);
  1441.       win->numr -= (hv ? where : 0);
  1442.       win->win_curow = curow;
  1443.       win->win_cucol = cucol;
  1444.  
  1445.       new->flags = WIN_EDGES | WIN_EDGE_REV;    /* Mplan defaults */
  1446.       new->lh_wid = 0;        /* For now */
  1447.       new->link = link;
  1448.  
  1449.       new->win_over = win->win_over + (hv ? -win->lh_wid : win->numc);
  1450.       new->win_down = win->win_down + (hv ? win->numr + 1 : 0);
  1451.       new->numc = (hv ? win->numc + win->lh_wid : where);
  1452.       new->numr = (hv ? where - 1 : win->numr);
  1453.       new->win_curow = curow;
  1454.       new->win_cucol = cucol;
  1455.       set_numcols (new, curow);
  1456.       recenter_window (win);
  1457.       recenter_window (new);
  1458.     }
  1459.   if (opts)
  1460.     {
  1461.       char *np;
  1462.       while (np =(char *) index (opts, ','))
  1463.     {
  1464.       *np = '\0';
  1465.       set_options (opts);
  1466.       *np++ = ';';
  1467.       opts = np;
  1468.     }
  1469.       if (np = (char *)rindex (opts, '\n'))
  1470.     *np = '\0';
  1471.       set_options (opts);
  1472.     }
  1473. }
  1474.  
  1475.  
  1476.  
  1477. static struct mouse_event *current_mouse;
  1478. static struct mouse_event *free_mouse;
  1479. static int mouse_id = 0;
  1480.  
  1481. #ifdef __STDC__
  1482. static void 
  1483. init_mouse (void)
  1484. #else
  1485. static void 
  1486. init_mouse ()
  1487. #endif
  1488. {
  1489.   current_mouse = free_mouse =
  1490.   (struct mouse_event *) ck_malloc (sizeof (struct mouse_event));
  1491.   free_mouse->next = free_mouse;
  1492.   free_mouse->prev = free_mouse;
  1493. }
  1494.  
  1495. static int mouse_location ();
  1496.  
  1497. #ifdef __STDC__
  1498. int 
  1499. enqueue_mouse_event (int r, int c, int button, int downp)
  1500. #else
  1501. int 
  1502. enqueue_mouse_event (r, c, button, downp)
  1503.      int r;
  1504.      int c;
  1505.      int button;
  1506.      int downp;
  1507. #endif
  1508. {
  1509.   struct mouse_event *m = free_mouse;
  1510.   if (m->next == current_mouse)
  1511.     {
  1512.       m->next =
  1513.     (struct mouse_event *) ck_malloc (sizeof (struct mouse_event));
  1514.       m->next->prev = m;
  1515.       m->next->next = current_mouse;
  1516.       current_mouse->prev = m->next;
  1517.       m->seq = mouse_id++;
  1518.       if (m->seq > 255)
  1519.     panic ("Too many mouse events enqueued.");
  1520.     }
  1521.   free_mouse = m->next;
  1522.   m->row = r;
  1523.   m->col = c;
  1524.   m->button = button;
  1525.   m->downp = downp;
  1526.   m->location = mouse_location (&m->r, &m->c, m);
  1527.   return m->seq;
  1528. }
  1529.  
  1530. #ifdef __STDC__
  1531. void 
  1532. dequeue_mouse_event (struct mouse_event *out, int seq)
  1533. #else
  1534. void 
  1535. dequeue_mouse_event (out, seq)
  1536.      struct mouse_event *out;
  1537.      int seq;
  1538. #endif
  1539. {
  1540.   free_mouse->seq = seq;
  1541.   while (current_mouse->seq != seq)
  1542.     current_mouse = current_mouse->next;
  1543.   if (current_mouse == free_mouse)
  1544.     {
  1545.       out->seq = seq;
  1546.       out->button = MOUSE_QERROR;
  1547.       return;
  1548.     }
  1549.   *out = *current_mouse;
  1550.   out->next = out->prev = 0;
  1551.   current_mouse = current_mouse->next;
  1552. }
  1553.  
  1554.  
  1555.  
  1556. #ifdef __STDC__
  1557. void 
  1558. io_init_windows (int sl, int sc, int ui, int us, int ir, int sr,
  1559.          int lr, int lc) 
  1560. #else
  1561. void 
  1562. io_init_windows (sl, sc, ui, us, ir, sr, lr, lc)
  1563.      int sl, sc;
  1564.      int ui, us;
  1565.      int ir, sr;
  1566.      int lr, lc;
  1567. #endif
  1568. {
  1569.   print_width = 80;        /* default ascii print width */
  1570.   scr_lines = sl;
  1571.   scr_cols = sc;
  1572.   input_rows = ir;
  1573.   status_rows = sr;
  1574.   label_rows = lr;
  1575.   label_emcols = lc;
  1576.   io_set_input_status (ui, us, 0);
  1577.   nwin = 1;
  1578.   wins = cwin = ck_malloc (sizeof (struct window));
  1579.   wins->id = win_id++;
  1580.   wins->win_over = 0;        /* This will be fixed by a future set_numcols */
  1581.   wins->win_down = (label_rows
  1582.             + (user_status > 0) * status_rows
  1583.             + (user_input > 0) * input_rows);
  1584.   wins->flags = WIN_EDGES | WIN_EDGE_REV;
  1585.   wins->numr = (scr_lines - label_rows - !!user_status * status_rows
  1586.         - input_rows - default_bottom_border);
  1587.   wins->numc = scr_cols - default_right_border;
  1588.   wins->bottom_edge_r = default_bottom_border;
  1589.   wins->right_edge_c = default_right_border;
  1590.   wins->link = -1;
  1591.   wins->lh_wid = 0;
  1592.   wins->win_curow = MIN_ROW;
  1593.   wins->win_cucol = MIN_COL;
  1594.   wins->win_slops = 0;
  1595.   init_mouse ();
  1596. }
  1597.  
  1598. #ifdef __STDC__
  1599. static int 
  1600. mouse_location (CELLREF *cr, CELLREF *cc, struct mouse_event *ev)
  1601. #else
  1602. static int 
  1603. mouse_location (cr, cc, ev)
  1604.      CELLREF *cr;
  1605.      CELLREF *cc;
  1606.      struct mouse_event *ev;
  1607. #endif
  1608. {
  1609.   int n;
  1610.   if (ev->row >= input && ev->row <= input + input_rows)
  1611.     return MOUSE_ON_INPUT;
  1612.   if (user_status && ev->row >= status
  1613.       && ev->row <= status + status_rows)
  1614.     return MOUSE_ON_STATUS;
  1615.   for (n = 0; n < nwin; ++n)
  1616.     {
  1617.       struct window *w = &wins[n];
  1618.       if (ev->row >= w->win_down
  1619.       && ev->row < w->win_down + w->numr
  1620.       && ev->col < w->win_over + w->numc
  1621.       && ev->col >= w->win_over)
  1622.     {
  1623.       int row_off = ev->row - w->win_down;
  1624.       int col_off = ev->col - w->win_over;
  1625.       int rh = 0;
  1626.       int cw = 0;
  1627.       CELLREF c, r;
  1628.       for (c = w->screen.lc; c <= w->screen.hc; ++c)
  1629.         if ((cw += get_scaled_width (c)) > col_off)
  1630.           break;
  1631.       *cc = c;
  1632.       for (r = w->screen.lr; r <= w->screen.hr; ++r)
  1633.         if ((rh += get_scaled_height (r)) > row_off)
  1634.           break;
  1635.       *cr = r;
  1636.       return n;
  1637.     }
  1638.     }
  1639.   return MOUSE_ON_EDGE;
  1640. }
  1641.  
  1642.